package com.test;

import java.io.*;

import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.portlet.*;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import tavernacon.DataResource;
import tavernacon.DataValue;
import tavernacon.RESTClient;

public class Portal168 extends GenericPortlet {

    public void processAction(ActionRequest request, ActionResponse response) throws PortletException, java.io.IOException {

        PortletSession session = request.getPortletSession();

        //get which workflow has been selected by user
        String workflow = request.getParameter("workflow");

        //set this workflow as a session-scoped variable
        if (workflow != null) {
            session.setAttribute("workflow", workflow);
        }

        //get the input names to the workflow
        String[] inputs = (String[]) session.getAttribute("inputKeys");
        System.out.println("Workflow: " + workflow);

        if (inputs != null) {
            runWorkflow(request);
        }

    }

    protected void doView(RenderRequest request, RenderResponse response)
            throws PortletException, IOException {

        PortletSession session = request.getPortletSession();

        String workflow = (String) session.getAttribute("workflow");

        if (workflow == null) {
            String url = "/WEB-INF/jsp/Portal168_view.jsp";
            getPortletContext().getRequestDispatcher(url).include(request, response);
        } else {
            try {

                createInterface(response, request);
            } catch (ParserConfigurationException ex) {
                Logger.getLogger(Portal168.class.getName()).log(Level.SEVERE, null, ex);
            } catch (SAXException ex) {
                Logger.getLogger(Portal168.class.getName()).log(Level.SEVERE, null, ex);
            } catch (XPathExpressionException ex) {
                Logger.getLogger(Portal168.class.getName()).log(Level.SEVERE, null, ex);
            }
            
            String url = "/WEB-INF/jsp/Portal168_view.jsp";
            getPortletContext().getRequestDispatcher(url).include(request, response);

        }
    }

    public void createInterface(RenderResponse response, RenderRequest request) throws IOException, ParserConfigurationException, SAXException, XPathExpressionException {

        PortletSession session = request.getPortletSession();
        String workflow = (String) session.getAttribute("workflow");
        String[] inputKeys;

        //Get workflow information in xml file
        InputStream inputStream = Portal168.class.getClassLoader().getResourceAsStream("../Workflows/" + workflow + ".xml");
        BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));
        String line = br.readLine();
        String xml = "";
        while (line != null) {
            System.out.println(line);
            xml += line;
            line = br.readLine();
        }

        //create a temporary file that can be parsed using XPath
        File temp = new File("interface");
        BufferedWriter bw = null;
        //String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><SOMETAG>Content</SOMETAG>";

        PrintWriter w = new PrintWriter(temp);
        bw = new BufferedWriter(w);
        bw.write(xml);
        bw.flush(); //<---- Make sure you flush the buffer contents into the file.

        DocumentBuilderFactory Factory = DocumentBuilderFactory.newInstance();
        Factory.setNamespaceAware(true);
        DocumentBuilder builder = Factory.newDocumentBuilder();
        Document doc = builder.parse(temp);
        //creating an XPathFactory:
        XPathFactory factory = XPathFactory.newInstance();
        //using this factory to create an XPath object:
        XPath xpath = factory.newXPath();

        XPathExpression descExpr = xpath.compile("/workflow/description/text()");
        Object descResult = descExpr.evaluate(doc, XPathConstants.NODESET);
        NodeList descNodeList = (NodeList) descResult;

        XPathExpression IDExpr = xpath.compile("/workflow/idonserver/text()");
        Object IDResult = IDExpr.evaluate(doc, XPathConstants.NODESET);
        NodeList IDNodeList = (NodeList) IDResult;

        XPathExpression locationExpr = xpath.compile("/workflow/serverLocation/text()");
        Object locationResult = locationExpr.evaluate(doc, XPathConstants.NODESET);
        NodeList locationNodeList = (NodeList) locationResult;

        XPathExpression typeExpr = xpath.compile("//inputs/input/type/text()");
        Object typeResult = typeExpr.evaluate(doc, XPathConstants.NODESET);
        NodeList typeNodeList = (NodeList) typeResult;

        XPathExpression nameExpr = xpath.compile("//inputs/input/name/text()");
        Object nameResult = nameExpr.evaluate(doc, XPathConstants.NODESET);
        NodeList nameNodeList = (NodeList) nameResult;

        XPathExpression exampleExpr = xpath.compile("//inputs/input/example/text()");
        Object exampleResult = exampleExpr.evaluate(doc, XPathConstants.NODESET);
        NodeList exampleNodeList = (NodeList) exampleResult;

        XPathExpression descriptionExpr = xpath.compile("//inputs/input/description/text()");
        Object descriptionResult = descriptionExpr.evaluate(doc, XPathConstants.NODESET);
        NodeList descriptionNodeList = (NodeList) descriptionResult;


        inputKeys = new String[typeNodeList.getLength()];
        String[] inputDescriptions = new String[typeNodeList.getLength()];
        String[] inputExamples = new String[typeNodeList.getLength()];

        for (int i = 0; i < typeNodeList.getLength(); i++) {
            inputKeys[i] = nameNodeList.item(i).getNodeValue();
            inputDescriptions[i] = descriptionNodeList.item(i).getNodeValue();
            inputExamples[i] = exampleNodeList.item(i).getNodeValue();
        }

        String description = (String) descNodeList.item(0).getNodeValue();
        String serverLocation = (String) locationNodeList.item(0).getNodeValue();

        //set all the workflow's attributes as session-scoped
        session.setAttribute("description", description);
        session.setAttribute("location", serverLocation);
        session.setAttribute("inputKeys", inputKeys);
        session.setAttribute("inputDescriptions", inputDescriptions);
        session.setAttribute("inputExamples", inputExamples);

        String workflowID = IDNodeList.item(0).getNodeValue();
        session.setAttribute("workflowID", workflowID);

    }

    public String runWorkflow(ActionRequest request) {

        PortletSession session = request.getPortletSession();
        String[] inputKeys = (String[]) session.getAttribute("inputKeys");
        String workflow = (String) session.getAttribute("workflow");

        System.out.println("Running workflow: " + workflow);

        String jobIdStr = "";
        boolean run = true;

        System.out.println("run");
        try {

            String[] inputValues = new String[inputKeys.length];
            for (int i = 0; i < inputKeys.length; i++) {
                inputValues[i] = request.getParameter(inputKeys[i]);
                if (inputValues[i] == null) {
                    run = false;
                }
            }

            for (int i = 0; i < inputValues.length; i++) {
                System.out.println(inputKeys[i] + ": " + inputValues[i]);
            }

            //boolean check to see if any values have been entered into 
            if (run) {
                //get workflow details
                InputStream inputStream = Portal168.class.getClassLoader().getResourceAsStream("../Workflows/" + workflow + ".xml");
                BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));
                String line = br.readLine();
                String xml = "";
                while (line != null) {
                    xml += line;
                    line = br.readLine();
                }

                //create a temporary file to parse with XPath
                File temp = new File("interface");
                BufferedWriter bw = null;
                //String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><SOMETAG>Content</SOMETAG>";

                PrintWriter w = new PrintWriter(temp);
                bw = new BufferedWriter(w);
                bw.write(xml);
                bw.flush(); //<---- Make sure you flush the buffer contents into the file.

                RESTClient tavernaRESTClient = new RESTClient();
                tavernaRESTClient.setBaseURL((String)session.getAttribute("location"));

                Map<String, DataValue> ds = new HashMap<String, DataValue>();

                for (int i = 0; i < inputKeys.length; i++) {
                    ds.put(inputKeys[i], new DataValue(inputValues[i]));
                }

                Long inputID = tavernaRESTClient.addData(new DataResource(ds));
                System.out.println("DataId :" + inputID);

                String wfidStr = (String) session.getAttribute("workflowID");
                long wfid = Long.parseLong(wfidStr);
                Long jobID = tavernaRESTClient.addJob(wfid, inputID);
                jobIdStr = jobID.toString();
                System.out.println("JobId :" + jobIdStr);
                session.setAttribute("jobID", jobIdStr);
                session.setAttribute("workflow", null);
                session.setAttribute("inputKeys", null);
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
        return jobIdStr;
    }

    //help mode method of portlet
    protected void doHelp(RenderRequest request, RenderResponse response)
            throws PortletException, IOException {

        response.setContentType("text/html");
        PrintWriter out = response.getWriter();

        out.write("This portlet runs <a href=\"http://www.taverna.org.uk\" target=\"_blank\">Taverna</a> workflows." +
                "<br/><br/>Selecting a workflow from the list and running it will give you back a job ID which can be used to look up results.");

    }
}
